/* 
 * Copyright [2018] [Alex/libo(liboms@hotmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.apidoc.analysis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.hyts.apidoc.config.AnalysisConfig;
import com.hyts.apidoc.model.ApiDefination;
import com.hyts.apidoc.model.ApiDoc;
import com.hyts.apidoc.model.ApiParam;
import com.hyts.apidoc.utility.StringUtils;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.Tag;

/**
 * @title AnalysisTemplate.java
 * @package com.hyts.apidoc.analysis
 * @description TODO
 * @author libo/Alex
 * @email liboms@hotmail.com/liboware@163.com
 * @date 2018年4月24日
 * @version V1.0
 */
public class AnalysisTemplate {

    /**
     * <p>
     * api文档Doc对象
     * </p>
     * 
     * @fieldName apiDoc
     * @fieldType ApiDoc
     */
    private ApiDoc apiDoc;

    /**
     * @fieldName tags
     * @fieldType Tag[]
     */
    private Tag[] tags;

    /**
     * @fieldName methodDoc
     * @fieldType MethodDoc
     */
    private MethodDoc methodDoc;

    /**
     * @constructor：AnalysisTemplate
     * @param apiDoc
     */
    public AnalysisTemplate(ApiDoc apiDoc, Tag[] tags) {
        super();
        this.apiDoc = apiDoc;
        this.tags = tags;
    }

    /**
     * @constructor：AnalysisTemplate
     * @param methdDoc
     */
    public AnalysisTemplate(MethodDoc methdDoc, ApiDoc apiDoc, Tag[] tags) {
        super();
        this.apiDoc = apiDoc;
        this.methodDoc = methdDoc;
        this.tags = tags;
    }

    /**
     * @return @exception
     */
    public AnalysisTemplate injectTypeHeader() {
        // 循环遍历数据信息
        for (AnalysisConfig config : AnalysisConfig.INSTANCE.getValues()) {
            for (int i = 0; i < tags.length; i++) {
                if (config.getCode().equalsIgnoreCase(tags[i].name())) {
                    switch (config) {
                    case EXT_TYPE_HEADER_TITLE_NAME:
                        apiDoc.setApiTypeName(tags[i].text());
                        break;
                    case TYPE_HEADER_TITLE_DESC:
                        apiDoc.setApiDescription(tags[i].text().replaceAll("\n|\r|\t|\\s", " "));
                        break;
                    case TYPE_HEADER_TITLE_AUTHOR:
                        apiDoc.setAuthor(tags[i].text());
                        break;
                    case TYPE_HEADER_TITLE_DATE:
                        apiDoc.setDate(tags[i].text());
                        break;
                    case TYPE_HEADER_TITLE_VERSION:
                        apiDoc.setVersion(tags[i].text());
                        break;
                    case TYPE_HEADER_TITLE_PACKAGE:
                        apiDoc.setPackageName(tags[i].text());
                        break;
                    default:
                        break;
                    }
                }
            }
        }
        return this;
    }

    /**
     * @exception
     */
    public AnalysisTemplate injectMethodHeader() {
        // 循环遍历数据信息
        if (apiDoc.getApiDefinationList() == null || apiDoc.getApiDefinationList().isEmpty()) {
            apiDoc.setApiDefinationList(new ArrayList<ApiDefination>());
        }
        // 创建局部异常列表
        List<String> localExceptionList = new ArrayList<>();
        // 创建参数列表
        List<ApiParam> localInParamList = new ArrayList<>();
        List<ApiParam> localoutParamList = new ArrayList<>();
        ApiDefination defination = new ApiDefination();
        defination.setPackageName(methodDoc.containingPackage().name());
        defination.setName(methodDoc.name());
        defination.setDescription(methodDoc.commentText());
        for (int i = 0; i < tags.length; i++) {
            for (AnalysisConfig config : AnalysisConfig.INSTANCE.getValues()) {
                if (config.getCode().equalsIgnoreCase(tags[i].name())) {
                    switch (config) {
                    case METHOD_HEADER_EXCEPTION:
                        localExceptionList.add(tags[i].text());
                        break;
                    case METHOD_HEADER_THROWS:
                        localExceptionList.add(tags[i].text());
                        break;
                    case METHOD_HEADER_RETURN:
                        ApiParam outParam = new ApiParam();
                        // 暂时默认都为是-必填
                        outParam.setIsRequired("是");
                        if (StringUtils.isBlank(tags[i].text())) {
                            outParam.setParamType(methodDoc.returnType().qualifiedTypeName());
                            outParam.setParamName("");
                            outParam.setParamDescription(methodDoc.modifiers()+" "+methodDoc.returnType().qualifiedTypeName());
                        } else {
                            outParam.setParamName(tags[i].text());
                            outParam.setParamType(methodDoc.returnType().qualifiedTypeName());
                            outParam.setParamDescription(tags[i].text());
                        }
                        localoutParamList.add(outParam);
                        break;
                    case METHOD_HEADER_PARAM:
                        ApiParam inParam = new ApiParam();
                        inParam.setIsRequired("是");
                        for (Parameter param : methodDoc.parameters()) {
                            if(StringUtils.isBlank(tags[i].text())) {
                                inParam.setParamName(param.name());
                                inParam.setParamType(param.typeName());
                                inParam.setParamDescription(param.typeName()+":"+param.name());  

                            }else if (param.name().equals(tags[i].text())) {
                                inParam.setParamType(param.typeName());
                                inParam.setParamName(param.name());
                                inParam.setParamDescription(tags[i].text());
                            }
                            localInParamList.add(inParam);
                        }
                        /*
                         * if(StringUtils.isBlank(tags[i].text())) {
                         * inParam.setParamType(methodDoc.parameters()[i]); inParam.setParamName("");
                         * inParam.setParamDescription(methodDoc.returnType().qualifiedTypeName());
                         * }else { inParam.setParamName(tags[i].text());
                         * inParam.setParamType(methodDoc.returnType().qualifiedTypeName());
                         * inParam.setParamDescription(tags[i].text()); }
                         */
                        break;
                    case METHOD_HEADER_NAME:
                        if(StringUtils.isBlank(tags[i].text())) {
                            defination.setName(methodDoc.name());
                        }else
                            defination.setName(tags[i].text());
                        break;
                    default:
                        break;
                    }
                }
            }

        }
        defination.setPackageName(apiDoc.getPackageName());
        defination.setExceptionList(localExceptionList);
        defination.setInputParameters(localInParamList);
        defination.setOutputParameters(localoutParamList);
        apiDoc.getApiDefinationList().add(defination);
        return this;
    }

    /**
     * @name apiDoc's getter method
     * @return apiDoc
     */
    public ApiDoc getApiDoc() {
        return apiDoc;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(AnalysisConfig.INSTANCE.getValues()));
    }

}
